package com.luckyframe.common.netty.jmeter;

import com.luckyframe.common.netty.Result;
import com.luckyframe.project.jmeter.jmeterNode.domain.JmeterNode;
import com.luckyframe.project.jmeter.jmeterNode.enums.JmeterNodeStatus;
import com.luckyframe.project.jmeter.jmeterNode.service.IJmeterNodeService;
import com.luckyframe.project.system.client.mapper.ClientMapper;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.concurrent.GenericFutureListener;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class JmeterNetty {

    @Autowired
    private ClientMapper clientMapper;

    @Autowired
    private IJmeterNodeService jmeterNodeService;

    @Autowired
    private JmeterChannelMap jmeterChannelMap;

    //logger
    private static final Logger log = LoggerFactory.getLogger(JmeterNetty.class);

    public static final HashMap<String,String> clientMap=new HashMap<>();


    public void start(InetSocketAddress address){
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {

            //重置客户端状态
            List<JmeterNode> jmeterNodes = jmeterNodeService.selectJmeterNodeList(new JmeterNode());
            if(CollectionUtils.isNotEmpty(jmeterNodes)){
                for (JmeterNode jmeterNode : jmeterNodes) {
                    jmeterNode.setStatus(JmeterNodeStatus.DOWN.getCode());
                    jmeterNode.setRemark("服务端启动重新初始化");
                    jmeterNodeService.updateJmeterNode(jmeterNode);
                }
            }

            ServerBootstrap bootstrap = new ServerBootstrap()
                    .group(bossGroup,workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    .childHandler(new ChannelInitializer<Channel>() {
                        @Override
                        protected void initChannel(Channel ch) throws Exception {
                            ByteBuf delimiter = Unpooled.copiedBuffer("$_".getBytes());
                            ch.pipeline().addLast(new DelimiterBasedFrameDecoder(Integer.MAX_VALUE, delimiter));
                            ch.pipeline().addLast("decoder",new StringDecoder(Charset.forName("GBK")));
                            ch.pipeline().addLast("encoder",new StringDecoder(Charset.forName("GBK")));
                            ch.pipeline().addLast(new IdleStateHandler(10,0,0,TimeUnit.SECONDS));
                            ch.pipeline().addLast("handler", new JmeterHandler());
                        }
                    });
            // 绑定端口，开始接收进来的连接
            ChannelFuture future = bootstrap.bind(address).sync();
            log.info("服务端启动成功，监听端口 " + address.getPort());


            future.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }


    public Result writeMsg(String msg, Long id , GenericFutureListener listener) {
        // 获取锁
        try {
            Channel channel = jmeterChannelMap.get(id.toString());
            if(channel != null){
                if(channel.isOpen()){

                    //channel.writeAndFlush(obj).sync();
                    ChannelFuture channelFuture = channel.writeAndFlush(Unpooled.copiedBuffer((msg + "$_").getBytes()));

                    if(listener!=null){
                        channelFuture.addListener(listener);
                    }

                    return new Result(1,"成功",null,null);
                }else{
                    return new Result(0,"客户端已关闭!",null,null);
                }
            }

        }catch (Exception e){
            e.printStackTrace();
            return new Result(0,"服务出错!",null,null);

        }finally {

        }
        return new Result(0,"客户端没有连接!",null,null);
    }
    public Result writeMsg(String msg, Long id){
        return writeMsg(msg,id,null);
    }




    public Result writeMsgSync(String msg, Long id) {
        // 获取锁
        try {
            Channel channel = jmeterChannelMap.get(id.toString());
            if(channel != null){
                if(channel.isOpen()){
                    // 设置同步
                    //channel.writeAndFlush(obj).sync();
                    channel.writeAndFlush(Unpooled.copiedBuffer((msg + "$_").getBytes())).sync();
                    return new Result(1,"成功",null,null);
                }else{
                    return new Result(0,"客户端已关闭!",null,null);
                }
            }

        }catch (Exception e){
            e.printStackTrace();
            return new Result(0,"服务出错!",null,null);

        }finally {

        }
        return new Result(0,"客户端没有连接!",null,null);
    }

}
